using AutoMapper;
using B.S.Data.MES.API.Applications.AccountApplication.Command;
using B.S.Data.MES.API.Dto.LoginDTO;
using B.S.Domain.Accounts;
using B.S.Infratrctrue;
using B.S.Requst;
using MD5Hash;
using MediatR;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Net.Mail;
using System.Security.Claims;
using System.Text;
using System.Transactions;

namespace B.S.Data.MES.API.Applications.AccountApplication.CommandHandler
{
    /// <summary>
    /// 实现任务
    /// </summary>
    public class LoginCommandHandler : IRequestHandler<LoginCommand, APIRequst<UserDTO>>
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="accountRepository">用户表</param>
        /// <param name="rouleRepository">角色表</param>
        /// <param name="userrouleRepository">用户权限表</param>
        public LoginCommandHandler(IBaseRepository<Account> accountRepository,IBaseRepository<RoleEntty> rouleRepository,IBaseRepository<UserRole> userrouleRepository,IMapper mapper,IBaseRepository<LoginLogger> loginloggerRepository)
        {
            AccountRepository = accountRepository;
            RouleRepository = rouleRepository;
            UserrouleRepository = userrouleRepository;
            Mapper = mapper;
            LoginloggerRepository = loginloggerRepository;
        }
        /// <summary>
        /// 用户表
        /// </summary>
        public IBaseRepository<Account> AccountRepository { get; }
        /// <summary>
        /// 角色表
        /// </summary>
        public IBaseRepository<RoleEntty> RouleRepository { get; }
        /// <summary>
        /// 用户角色表
        /// </summary>
        public IBaseRepository<UserRole> UserrouleRepository { get; }
        public IMapper Mapper { get; }
        public IBaseRepository<LoginLogger> LoginloggerRepository { get; }

        public async Task<APIRequst<UserDTO>> Handle(LoginCommand request, CancellationToken cancellationToken)
        {
            var path = AccountRepository.GetAll();
            var pats = RouleRepository.GetAll();
            var pata = UserrouleRepository.GetAll();

                var list = from a in path
                           join b in pata on a.UserId equals b.UserId
                           join c in pats on b.RoleId equals c.RoleId
                           where a.UserName == request.UserName
                           select new UserDTO
                           {
                               UserId = a.UserId,
                               UserName = a.UserName,
                               UserPass = a.UserPass,
                               UserNickname = a.UserNickname,
                               Iocn = a.Iocn,
                               factoryId = a.factoryId,
                               Sex = a.Sex,
                               DeptId = a.DeptId,
                               RoleId=b.RoleId,
                               RoleName = c.RoleName,
                               Massage = c.Massage,
                           };
            var listDto = list.FirstOrDefault();
            
            //记录登录日志
            request.data.Account = request.UserName ?? string.Empty;
            
            // 使用从请求中获取的客户端IP地址
            string clientIp = request.ClientIp ?? "127.0.0.1";
            request.data.LogIp = clientIp;
            
            // 获取IP对应的地理位置信息（省份到县级）
            request.data.Addr = GetLocationFromIp(clientIp);
            
            // 设置登录时间
            request.data.CreateTime = DateTime.Now;
            
            // 保存登录日志
            await LoginloggerRepository.Add(request.data);

            if (listDto == null)
            {
                return new APIRequst<UserDTO>
                {
                    Code = RequstCode.失败,
                    Msg = "账号不存在",
                    Data = null
                };
            }

            if(listDto.UserPass!=request.UserPass.GetMD5().ToUpper())
            {
                return new APIRequst<UserDTO>
                {
                    Code = RequstCode.失败,
                    Msg = "密码错误",
                    Data = null
                };
            }

           

            return new APIRequst<UserDTO>
            {
                Code = RequstCode.成功,
                Msg = "登录成功",
                Token = CreateTokenString(listDto),
                Data = listDto
            };

        }
        
        /// <summary>
        /// 根据IP地址获取真实地理位置信息（省份到县级）
        /// 使用百度地图IP定位API
        /// </summary>
        /// <param name="ipAddress">IP地址</param>
        /// <returns>地理位置信息（省份 城市 区县格式）</returns>
        private string GetLocationFromIp(string ipAddress)
        {
            try
            {
                // 本地测试环境使用默认值
                if (ipAddress == "127.0.0.1" || ipAddress.StartsWith("192.168.") || ipAddress.StartsWith("10."))
                {
                    return "北京市 北京市 海淀区";
                }
                
                // 百度地图IP定位API密钥
                string ak = "cP1hBZPDEiq1qk9ZsQrZnUNLlH3kZkze";
                string apiUrl = $"https://api.map.baidu.com/location/ip?ak={ak}&ip={ipAddress}&coor=bd09ll";
                
                using (var httpClient = new HttpClient())
                {
                    // 设置请求超时时间为5秒
                    httpClient.Timeout = TimeSpan.FromSeconds(5);
                    
                    // 发送GET请求获取地理位置信息
                    var response = httpClient.GetStringAsync(apiUrl).Result;
                    
                    // 解析JSON响应
                    var result = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(response);
                    
                    // 检查API调用是否成功
                    if (result != null && result["status"]?.ToString() == "0")
                    {
                        // 获取地址信息
                        var content = result["content"];
                        if (content != null)
                        {
                            var addressDetail = content["address_detail"];
                            if (addressDetail != null)
                            {
                                // 获取省份、城市和区县
                                string province = addressDetail["province"]?.ToString() ?? "";
                                string city = addressDetail["city"]?.ToString() ?? "";
                                string district = addressDetail["district"]?.ToString() ?? "";
                                
                                // 返回格式：省份 城市 区县
                                return $"{province} {city} {district}";
                            }
                        }
                    }
                }
                
                // API调用失败时返回默认值
                return "北京市 北京市 朝阳区";
            }
            catch (Exception ex)
            {
                // 发生异常时记录日志并返回默认值
                // 注意：实际项目中应该有日志记录
                return "未知位置";
            }
        }
        


        private string CreateTokenString(UserDTO user)
        {
            //私钥
            var secretByte = Encoding.UTF8.GetBytes("kdsfldsflkdslkflkdsflkdslfdslkflk");
            // 非对称加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            // 使用256 生成数字签名
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
            var claims = new[]
            {
                new Claim("UserId",user.UserId.ToString()),
                new Claim("UserNickname",user.UserNickname),
                new Claim("RoleId",user.RoleId.ToString()),
                new Claim("RoleName",user.RoleName),
            };
            // 生成Token
            var token = new JwtSecurityToken(
                issuer: "BeiJingBW",
                audience: "BeiJingBW",
                expires: DateTime.Now.AddDays(1), // 一天后过期
                claims: claims,
                signingCredentials: signingCredentials
            );
            // 写入Redis
            //RedisHelper.Set("Token", strToken, 10);
            return token.ToString();
        }
    }
}
